using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Security.Permissions;

[assembly: CLSCompliant(true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
namespace AsciiPaint
{

 public partial class MainForm : Form
 {
  /*//imports
  public static int WSB_PROP_CYVSCROLL = 0x00000001;
  public static int WSB_PROP_CXHSCROLL = 0x00000002;
  public static int WSB_PROP_CYHSCROLL = 0x00000004;
  public static int WSB_PROP_CXVSCROLL = 0x00000008;
  public static int WSB_PROP_CXHTHUMB = 0x00000010;
  public static int WSB_PROP_CYVTHUMB = 0x00000020;
  public static int WSB_PROP_VBKGCOLOR = 0x00000040;
  public static int WSB_PROP_HBKGCOLOR = 0x00000080;
  public static int WSB_PROP_VSTYLE = 0x00000100;
  public static int WSB_PROP_HSTYLE = 0x00000200;
  public static int WSB_PROP_WINSTYLE = 0x00000400;
  public static int WSB_PROP_PALETTE = 0x00000800;
  public static int WSB_PROP_MASK = 0x00000FFF;

  public static int FSB_FLAT_MODE = 2;
  public static int FSB_ENCARTA_MODE = 1;
  public static int FSB_REGULAR_MODE = 0;

  public static int SB_HORZ = 0;
  public static int SB_VERT = 1;
  public static int SB_CTL = 2;
  public static int SB_BOTH = 3;

  [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
  public static extern bool InitializeFlatSB(int hWnd);
  [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
  public static extern bool FlatSB_SetScrollProp(int hWnd, int index, IntPtr newValue, bool fRedraw);
  [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
  public static extern bool UninitializeFlatSB(int hWnd);
  [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
  public static extern int FlatSB_SetScrollPos(int hWnd, int code, int nPos, bool fRedraw);
  [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
  public static extern int FlatSB_SetScrollRange(int hWnd, int code, int nMinPos, int nMaxPos, bool fRedraw);
  */
  //
  int oldX = -1;
  int oldY = -1;
  int asciiW = 100;//width of ascii image
  int asciiH = 105;//height of ascii image
  int charW;//width of character
  int charH;//height of character
  //String empty_char = ":";
  String[] asciiImage;
  Color[] asciiColors;
  Graphics currentGraphics;
  bool mouseClicked;
  public MainForm()
  {
   InitializeComponent();
   //init flat scrollbars
   /* InitializeFlatSB((int)ToolPanel.Handle);
    FlatSB_SetScrollProp((int)ToolPanel.Handle, WSB_PROP_VSTYLE, (IntPtr)FSB_FLAT_MODE, true);   
    FlatSB_SetScrollProp((int)ToolPanel.Handle, WSB_PROP_CXVSCROLL, (IntPtr)8, true);
    int hei0 = ToolPanel.VerticalScroll.Minimum;
    int hei1 = ToolPanel.VerticalScroll.Maximum;
    FlatSB_SetScrollRange((int)ToolPanel.Handle, SB_VERT, hei0, hei1, true);*/
   //read palette
   XmlReaderSettings settings = new XmlReaderSettings();
   settings.ConformanceLevel = ConformanceLevel.Fragment;
   settings.IgnoreWhitespace = true;
   settings.IgnoreComments = true;
   XmlReader reader = XmlReader.Create("palette.xml", settings);
   colorList.Items.Clear();
   while (reader.Read())
   {
    if (reader.IsStartElement())
    {
     if (!reader.IsEmptyElement)
     {
      reader.Read(); // Read the start tag.
      colorList.Items.Add(reader.ReadString());  //Read the text content of the element.
     }
    }
   }
   //TODO: replace in future
   System.IO.TextReader streamReader = new System.IO.StreamReader("test.txt");
   asciiImage = new String[asciiH];
   asciiColors = new Color[asciiH * asciiW];
   for (int j = 0; j < asciiH; j++)
   {
    char[] sk = new char[asciiW + 2];
    streamReader.Read(sk, 0, asciiW + 2);
    asciiImage[j] = new String(sk);
    for (int i = 0; i < asciiW; i++)
    {
     asciiColors[j * asciiW + i] = Color.Black;
    }
   }
   streamReader.Close();
   //end of replacer
   charH = (int)toolPanel.Font.GetHeight();
   charW = (int)(charH / 1.333333) - 2;
   charH += 2;
   picture.Width = asciiW * charW;
   picture.Height = asciiH * charH;
   picture.Image = new Bitmap(asciiW * charW, asciiH * charH);
   currentGraphics = Graphics.FromImage(picture.Image);
   DrawPicture();
  }
  public void DrawPicture()
  {
   currentGraphics.Clear(backgroundColor.BackColor);
   currentGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
   for (int j = 0; j < asciiH; j++)
   {    
    for (int i = 0; i < asciiW; i++)
    {
     String ss = asciiImage[j][i].ToString(CultureInfo.CurrentCulture);
     currentGraphics.DrawString(ss, toolPanel.Font, new SolidBrush(asciiColors[j * asciiW + i]), i * charW, j * charH);
    }
   }
  }

  private void exitToolStripMenuItem_Click(object sender, EventArgs e)
  {
   Close();
  }

  private void Picture_MouseDown(object sender, MouseEventArgs e)
  {
   if (e.Button == MouseButtons.Left)
   {
    int cx = e.X / charW;
    int cy = e.Y / charH;
    DrawNow(cx, cy);
    picture.Refresh();
    mouseClicked = true;
   }
  }

  private void Picture_MouseMove(object sender, MouseEventArgs e)
  {
   int cx = e.X / charW;
   int cy = e.Y / charH;
   if (e.Button == MouseButtons.Left) DrawNow(cx, cy);
   //draw brush
   DrawBrush(backgroundColor.BackColor, oldX, oldY);
   if((cy>0)&&(cx>0)&&(cy<asciiH)&&(cx<asciiW))
    DrawBrush(asciiColors[cy * asciiW + cx], cx, cy);
   oldX = cx;
   oldY = cy;
   //refresh
   picture.Refresh();
  }

  private void Picture_MouseUp(object sender, MouseEventArgs e)
  {
   if (e.Button == MouseButtons.Left)
   {
    int cx = e.X / charW;
    int cy = e.Y / charH;
    DrawNow(cx, cy);
    picture.Refresh();
    mouseClicked = false;
   }
  }

  private void Picture_MouseLeave(object sender, EventArgs e)
  {
   mouseClicked = false;
   //draw brush
   DrawBrush(backgroundColor.BackColor, oldX, oldY);
   //refresh
   picture.Refresh();
  }

  private void trackBar1_ValueChanged(object sender, EventArgs e)
  {
   currentColor.BackColor = Color.FromArgb(redTrackBar.Value, greenTrackBar.Value, blueTrackBar.Value);
  }

  private void ColorCollapse_Click(object sender, EventArgs e)
  {
   colorPanel.Visible = !colorPanel.Visible;
  }

  private void CurrentColor_Click(object sender, EventArgs e)
  {
   chooseColorDialog.Color = currentColor.BackColor;
   if (chooseColorDialog.ShowDialog() == DialogResult.OK)
   {
    redTrackBar.Value = chooseColorDialog.Color.R;
    greenTrackBar.Value = chooseColorDialog.Color.G;
    blueTrackBar.Value = chooseColorDialog.Color.B;
   }
  }

  private void BackgroundColor_Click(object sender, EventArgs e)
  {
   chooseColorDialog.Color = backgroundColor.BackColor;
   if (chooseColorDialog.ShowDialog() == DialogResult.OK)
   {
    backgroundColor.BackColor = chooseColorDialog.Color;
   }
   DrawPicture();
   picture.Refresh();
  }
  private Point[] FindCircle(int x, int y, int radius)
  {
   //TODO: Create more correct alg
   if (radius == 0)
   {
    Point[] sk ={ new Point(x * charW, y * charH), new Point(x * charW + charW, y * charH), new Point(x * charW + charW, y * charH + charH), new Point(x * charW, y * charH + charH), new Point(x * charW, y * charH) };
    return sk;
   }
   int xx = radius;
   int yy = 0;
   List<Point> ls = new List<Point>();
   do
   {
    ls.Add(new Point(xx, yy));
    if ((xx - 1) * (xx - 1) + (yy + 1) * (yy + 1) == radius * radius)
    { xx--; yy++; }
    else
     if ((xx - 1) * (xx - 1) + (yy) * (yy) >= radius * radius)
      xx--;
     else
      yy++;
   } while ((xx != 0) || (yy != radius));
   ls.Add(new Point(xx, yy));
   List<Point> lp = new List<Point>();
   for (int i = 0; i < ls.Count; i++)
   {
    lp.Add(new Point(ls[i].X + 1, ls[i].Y + 1));
    if (i < ls.Count - 1)
    {
     if ((ls[i].X != ls[i + 1].X) && (ls[i].Y != ls[i + 1].Y))
     {
      lp.Add(new Point(ls[i].X, ls[i].Y + 1));
     }
    }
   }
   Point[] ret = new Point[lp.Count * 4 + 1];
   //
   // 2 1
   // 3 4
   //
   //1
   for (int i = 0; i < lp.Count; i++)
   {
    ret[i] = new Point(lp[i].X, lp[i].Y);
   }
   //2
   for (int i = 0; i < lp.Count; i++)
   {
    ret[i + lp.Count] = new Point(-lp[lp.Count - i - 1].X + 1, lp[lp.Count - i - 1].Y);
   }
   //3
   for (int i = 0; i < lp.Count; i++)
   {
    ret[i + 2 * lp.Count] = new Point(-lp[i].X + 1, -lp[i].Y + 1);
   }
   //4
   for (int i = 0; i < lp.Count; i++)
   {
    ret[i + 3 * lp.Count] = new Point(lp[lp.Count - i - 1].X, -lp[lp.Count - i - 1].Y + 1);
   }
   ret[ret.Length - 1] = new Point(lp[0].X, lp[0].Y);
   for (int i = 0; i < ret.Length; i++)
   {
    ret[i].X = ret[i].X * charW + x * charW + 1;
    ret[i].Y = ret[i].Y * charH + y * charH + 1;
   }
   return ret;
  }
  private void DrawBrush(Color cl, int x, int y)
  {
   if (x < 0) return;
   if (y < 0) return;
   if (x >= asciiW) return;
   if (y >= asciiH) return;

   //if color drawing
   if (colorPanel.Visible)
   {
    //if current tool is brush
    if (toolButtonBrush.Checked)
    {
     //if brush shape is quad
     if (toolButtonQuad.Checked)
     {
      currentGraphics.DrawRectangle(new Pen(cl), (x - innerTrackBar.Value + 1) * charW + 1, (y - innerTrackBar.Value + 1) * charH + 1, charW * (2 * innerTrackBar.Value - 1), charH * (2 * innerTrackBar.Value - 1));
      currentGraphics.DrawRectangle(new Pen(cl), (x - innerTrackBar.Value + 1 - outerTrackBar.Value) * charW + 1, (y - innerTrackBar.Value + 1 - outerTrackBar.Value) * charH + 1, charW * (2 * innerTrackBar.Value - 1 + 2 * outerTrackBar.Value), charH * (2 * innerTrackBar.Value - 1 + 2 * outerTrackBar.Value));
     }
     else//if current tool is brush
      if (toolButtonCircle.Checked)
      {
       currentGraphics.DrawLines(new Pen(cl), FindCircle(x, y, innerTrackBar.Value - 1));
       currentGraphics.DrawLines(new Pen(cl), FindCircle(x, y, innerTrackBar.Value + outerTrackBar.Value - 1));
      }
    }
    else
    {
     currentGraphics.DrawRectangle(new Pen(cl), x * charW + 1, y * charH + 1, charW, charH);
    }
   }
   //TODO: add b/w drawing
  }
  private static int ColorDistance(Color color1, Color color2)
  {
   int r1 = color1.R;
   int g1 = color1.G;
   int b1 = color1.B;
   int r2 = color2.R;
   int g2 = color2.G;
   int b2 = color2.B;
   int res = (r1 - r2) * (r1 - r2) + (g1 - g2) * (g1 - g2) + (b1 - b2) * (b1 - b2);
   return (int)Math.Sqrt(res)*3;
  }
  private struct FillState
  {
   public int x;
   public int y;
   public int state;
  };
  private void FillColor(Color fillColor, Color startColor, int x, int y, int opacity, int tolerance)
  {
   Stack<FillState> fillStates=new Stack<FillState>();
   FillState currentState;
   currentState.x = x;
   currentState.y = y;
   currentState.state = 0;
   while (true)
   {
    int i = currentState.x;
    int j = currentState.y;
    int c1 = opacity;
    int c2 = 100 - c1;
    asciiColors[j * asciiW + i] = Color.FromArgb(
                                           (int)((float)(fillColor.R * c1 + c2 * asciiColors[j * asciiW + i].R) / (float)100),
                                           (int)((float)(fillColor.G * c1 + c2 * asciiColors[j * asciiW + i].G) / (float)100),
                                           (int)((float)(fillColor.B * c1 + c2 * asciiColors[j * asciiW + i].B) / (float)100)
                                          );
    String ss = asciiImage[j][i].ToString(CultureInfo.CurrentCulture);
    currentGraphics.DrawString(ss, toolPanel.Font, new SolidBrush(asciiColors[j * asciiW + i]), i * charW, j * charH);
    //left
    if(currentState.state==0)
    {
     currentState.state++;
     if(i>0)
      if (ColorDistance(startColor, asciiColors[j * asciiW + i-1])<tolerance)
       if (asciiColors[j * asciiW + i - 1]!=fillColor)
       {
        fillStates.Push(currentState);
        currentState.state = 0;
        currentState.x = i - 1;
        currentState.y = j;
        continue;
       }       
    }
    //top
    if(currentState.state==1)
    {
     currentState.state++;
     if (j > 0)
      if (ColorDistance(startColor, asciiColors[(j-1) * asciiW + i]) < tolerance)
       if (asciiColors[(j-1) * asciiW + i] != fillColor)
       {
        fillStates.Push(currentState);
        currentState.state = 0;
        currentState.x = i;
        currentState.y = j-1;
        continue; 
       }       
    }
    //right
    if(currentState.state==2)
    {
     currentState.state++;
     if (i <asciiW-1)
      if (ColorDistance(startColor, asciiColors[j * asciiW + i + 1]) < tolerance)
       if (asciiColors[j * asciiW + i + 1] != fillColor)
       {
        fillStates.Push(currentState);
        currentState.state = 0;
        currentState.x = i + 1;
        currentState.y = j;
        continue; 
       }    
    }
    //bottom
    if(currentState.state==3)
    {
     currentState.state++;
     if (j <asciiH-1)
      if (ColorDistance(startColor, asciiColors[(j + 1) * asciiW + i]) < tolerance)
       if (asciiColors[(j + 1) * asciiW + i] != fillColor)
       {
        fillStates.Push(currentState);
        currentState.state = 0;
        currentState.x = i;
        currentState.y = j + 1;
        continue;
       }     
    }
    //next element of stack or end of cycle
    if(currentState.state==4)
    {
     if (fillStates.Count == 0) return;
     currentState = fillStates.Pop();
    }
   }
  }
  private void FillAscii(Color fillColor,Color startColor,int x,int y,int opacity, int tolerance)
  {
   //TODO:Write code.
  }
  private void DrawNow(int x, int y)
  {
   if (!mouseClicked) return;
   if ((y < 0) || (y >= asciiH) || (x < 0) || (x >= asciiW)) return;
   //if color drawing
   if (colorPanel.Visible)
   {
    //if current tool is brush
    if (toolButtonBrush.Checked)
    {
     //if brush shape is quad
     if (toolButtonQuad.Checked)
     {
      //fill solid&fade colors
      for (int i = x - innerTrackBar.Value - outerTrackBar.Value + 1; i <= x + innerTrackBar.Value + outerTrackBar.Value - 1; i++)
       for (int j = y - innerTrackBar.Value - outerTrackBar.Value + 1; j <= y + innerTrackBar.Value + outerTrackBar.Value - 1; j++)
       {
        if ((j < 0) || (j >= asciiH) || (i < 0) || (i >= asciiW)) continue;
        float coeff = 1;
        float kx = (float)(Math.Abs(i - x) - innerTrackBar.Value + 1);
        float ky = (float)(Math.Abs(j - y) - innerTrackBar.Value + 1);
        if (kx < 0) kx = 0;
        if (ky < 0) ky = 0;
        if ((kx <= 0) && (ky <= 0))
         coeff = 1;
        else
         coeff = ((float)(outerTrackBar.Value) - (float)Math.Sqrt(kx * kx + ky * ky) + 1) / (float)(outerTrackBar.Value + 1);
        int c1 = (int)((float)opacityTrackBar.Value * coeff);
        if (c1 > 100) c1 = 100;
        if (c1 < 0) c1 = 0;
        int c2 = 100 - c1;
        asciiColors[j * asciiW + i] = Color.FromArgb(
                                           (int)((float)(currentColor.BackColor.R * c1 + c2 * asciiColors[j * asciiW + i].R) / (float)100),
                                           (int)((float)(currentColor.BackColor.G * c1 + c2 * asciiColors[j * asciiW + i].G) / (float)100),
                                           (int)((float)(currentColor.BackColor.B * c1 + c2 * asciiColors[j * asciiW + i].B) / (float)100)
                                          );
        String ss = asciiImage[j][i].ToString(CultureInfo.CurrentCulture);
        currentGraphics.DrawString(ss, toolPanel.Font, new SolidBrush(asciiColors[j * asciiW + i]), i * charW, j * charH);
       }
     }
     else//if brush shape is circle
      if (toolButtonCircle.Checked)
      {
       //fill solid&fade colors
       //TODO: Shape of brush is incorrect
       for (int i = x - innerTrackBar.Value - outerTrackBar.Value + 1; i <= x + innerTrackBar.Value + outerTrackBar.Value - 1; i++)
        for (int j = y - innerTrackBar.Value - outerTrackBar.Value + 1; j <= y + innerTrackBar.Value + outerTrackBar.Value - 1; j++)
        {
         if ((j < 0) || (j >= asciiH) || (i < 0) || (i >= asciiW)) continue;
         int ii = i - x;
         int jj = j - y;
         float coeff = 1;
         float rad = (float)(ii * ii + jj * jj);
         if (rad >= innerTrackBar.Value * innerTrackBar.Value)
         {
          coeff = ((float)(outerTrackBar.Value) - ((float)Math.Sqrt(rad) - (float)innerTrackBar.Value)) / (float)(outerTrackBar.Value);
         }
         int c1 = (int)((float)opacityTrackBar.Value * coeff);
         if (c1 > 100) c1 = 100;
         if (c1 < 0) c1 = 0;
         int c2 = 100 - c1;
         asciiColors[j * asciiW + i] = Color.FromArgb(
                                            (int)((float)(currentColor.BackColor.R * c1 + c2 * asciiColors[j * asciiW + i].R) / (float)100),
                                            (int)((float)(currentColor.BackColor.G * c1 + c2 * asciiColors[j * asciiW + i].G) / (float)100),
                                            (int)((float)(currentColor.BackColor.B * c1 + c2 * asciiColors[j * asciiW + i].B) / (float)100)
                                           );
         String ss = asciiImage[j][i].ToString(CultureInfo.CurrentCulture);
         currentGraphics.DrawString(ss, toolPanel.Font, new SolidBrush(asciiColors[j * asciiW + i]), i * charW, j * charH);
        }
      }
    }
    else//dropper - color picker
    if (toolButtonDropper.Checked)
    {
     redTrackBar.Value = asciiColors[y * asciiW + x].R;
     greenTrackBar.Value = asciiColors[y * asciiW + x].G;
     blueTrackBar.Value = asciiColors[y * asciiW + x].B;
    }
    else//filler
    if (toolButtonFiller.Checked)
    {
     //fill from color
     if (toolButtonFillColor.Checked)
     {
      //recurrent fill function
      FillColor(currentColor.BackColor,asciiColors[y * asciiW + x], x, y,fillOpacityTrackBar.Value,fillToleranceTrackBar.Value);
     }
     else
     //fill from ascii character
     if (toolButtonFillAscii.Checked)
     {
      //recurrent fill function
      FillAscii(currentColor.BackColor, asciiColors[y * asciiW + x], x, y, fillOpacityTrackBar.Value, fillToleranceTrackBar.Value);
     }
    }
   }
   //TODO: add b/w drawing
  }

  private void toolStripButton4_Click(object sender, EventArgs e)
  {
   toolButtonQuad.Checked = true;
   toolButtonCircle.Checked = false;
  }

  private void ToolButtonCircle_Click(object sender, EventArgs e)
  {
   toolButtonQuad.Checked = false;
   toolButtonCircle.Checked = true;
  }

  private void InnerTrackBar_ValueChanged(object sender, EventArgs e)
  {
   innerEdit.Text = innerTrackBar.Value.ToString(CultureInfo.CurrentCulture);
  }

  private void OuterTrackBar_ValueChanged(object sender, EventArgs e)
  {
   outerEdit.Text = outerTrackBar.Value.ToString(CultureInfo.CurrentCulture);
  }

  private void OpacityTrackBar_ValueChanged(object sender, EventArgs e)
  {
   opacityEdit.Text = opacityTrackBar.Value.ToString(CultureInfo.CurrentCulture);
  }

  private void InnerEdit_TextChanged(object sender, EventArgs e)
  {
   innerTrackBar.Value = Convert.ToInt32(innerEdit.Text, CultureInfo.CurrentCulture);
  }

  private void OpacityEdit_TextChanged(object sender, EventArgs e)
  {
   opacityTrackBar.Value = Convert.ToInt32(opacityEdit.Text, CultureInfo.CurrentCulture);
  }

  private void OuterEdit_TextChanged(object sender, EventArgs e)
  {
   outerTrackBar.Value = Convert.ToInt32(outerEdit.Text, CultureInfo.CurrentCulture);
  }

  private void Form1_MouseCaptureChanged(object sender, EventArgs e)
  {
   //
  }

  private void ToolButtonBrush_Click(object sender, EventArgs e)
  {
   toolButtonBrush.Checked = true;
   toolButtonDropper.Checked = false;
   toolButtonFiller.Checked = false;
   brushPanel.Show();
   fillerPanel.Hide();
  }

  private void ToolButtonDropper_Click(object sender, EventArgs e)
  {
   toolButtonBrush.Checked = false;
   toolButtonDropper.Checked = true;
   toolButtonFiller.Checked = false;
   brushPanel.Hide();
   fillerPanel.Hide();
  }

  private void ToolButtonFiller_Click(object sender, EventArgs e)
  {
   toolButtonBrush.Checked = false;
   toolButtonDropper.Checked = false;
   toolButtonFiller.Checked = true;
   brushPanel.Hide();
   fillerPanel.Show();
  }

  private void ColorList_DrawItem(object sender, DrawItemEventArgs e)
  {
   int r = 0, g = 0, b = 0;
   string tx = colorList.Items[e.Index].ToString();
   int i1 = tx.IndexOf(';');
   int i2 = tx.LastIndexOf(';');
   r = Convert.ToInt32(tx.Substring(0, i1), CultureInfo.CurrentCulture);
   g = Convert.ToInt32(tx.Substring(i1 + 1, i2 - i1 - 1), CultureInfo.CurrentCulture);
   b = Convert.ToInt32(tx.Substring(i2 + 1, tx.Length - i2 - 1), CultureInfo.CurrentCulture);
   e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(r, g, b)), e.Bounds);
   if (e.Index == colorList.SelectedIndex)
   {
    e.Graphics.DrawRectangle(new Pen(Color.FromArgb(255 - r, 255 - g, 255 - b)), e.Bounds);
   }
  }

  private void toolStripButton2_Click(object sender, EventArgs e)
  {
   colorList.Items.Add(currentColor.BackColor.R.ToString(CultureInfo.CurrentCulture) + ";" + currentColor.BackColor.G.ToString(CultureInfo.CurrentCulture) + ";" + currentColor.BackColor.B.ToString(CultureInfo.CurrentCulture));
   colorList.Refresh();
  }

  private void toolStripButton3_Click(object sender, EventArgs e)
  {
   int index = colorList.SelectedIndex;
   if (index < 0) return;
   colorList.Items[index] = currentColor.BackColor.R.ToString(CultureInfo.CurrentCulture) + ";" + currentColor.BackColor.G.ToString(CultureInfo.CurrentCulture) + ";" + currentColor.BackColor.B.ToString(CultureInfo.CurrentCulture);
  }

  private void toolStripButton4_Click_1(object sender, EventArgs e)
  {
   int index = colorList.SelectedIndex;
   if (index < 0) return;
   colorList.Items.RemoveAt(index);
  }

  private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  {
   //save palette
   XmlWriterSettings settings = new XmlWriterSettings();
   settings.Indent = true;
   settings.IndentChars = ("    ");
   XmlWriter writer = XmlWriter.Create("palette.xml", settings);
   writer.WriteStartElement("palette");
   for (int i = 0; i < colorList.Items.Count; i++)
    writer.WriteElementString("color", colorList.Items[i].ToString());
   writer.WriteEndElement();
   writer.Flush();
   //destroy flat scrollbars
   //UninitializeFlatSB((int)ToolPanel.Handle);
   //save settings
   AsciiPaint.Properties.Settings sets = AsciiPaint.Properties.Settings.Default;
   sets.Left = Left;
   sets.Top = Top;
   sets.Width = Width;
   sets.Height = Height;
   sets.Save();
  }

  private void toolStripButton5_Click(object sender, EventArgs e)
  {
   palettePanel.Visible = !palettePanel.Visible;
  }


  private void ToolButtonFillColor_Click(object sender, EventArgs e)
  {
   toolButtonFillColor.Checked = true;
   toolButtonFillAscii.Checked = false;
  }

  private void ToolButtonFillAscii_Click(object sender, EventArgs e)
  {
   toolButtonFillColor.Checked = false;
   toolButtonFillAscii.Checked = true;
  }

  private void ColorList_SelectedIndexChanged(object sender, EventArgs e)
  {
   int index = colorList.SelectedIndex;
   if (index < 0) return;
   int r = 0, g = 0, b = 0;
   string tx = colorList.Items[index].ToString();
   int i1 = tx.IndexOf(';');
   int i2 = tx.LastIndexOf(';');
   r = Convert.ToInt32(tx.Substring(0, i1), CultureInfo.CurrentCulture);
   g = Convert.ToInt32(tx.Substring(i1 + 1, i2 - i1 - 1), CultureInfo.CurrentCulture);
   b = Convert.ToInt32(tx.Substring(i2 + 1, tx.Length - i2 - 1), CultureInfo.CurrentCulture);
   redTrackBar.Value = r;
   greenTrackBar.Value = g;
   blueTrackBar.Value = b;
   colorList.Refresh();
  }

  private void button1_Click(object sender, EventArgs e)
  {
   int r = 0, g = 0, b = 0;
   r = redTrackBar.Value;
   g = greenTrackBar.Value;
   b = blueTrackBar.Value;
   redTrackBar.Value = backgroundColor.BackColor.R;
   greenTrackBar.Value = backgroundColor.BackColor.G;
   blueTrackBar.Value = backgroundColor.BackColor.B;
   backgroundColor.BackColor = Color.FromArgb(r, g, b);
   DrawPicture();
   picture.Refresh();
  }

  private void button2_Click(object sender, EventArgs e)
  {
   redTrackBar.Value = backgroundColor.BackColor.R;
   greenTrackBar.Value = backgroundColor.BackColor.G;
   blueTrackBar.Value = backgroundColor.BackColor.B;
  }

  private void button3_Click(object sender, EventArgs e)
  {
   int r = 0, g = 0, b = 0;
   r = redTrackBar.Value;
   g = greenTrackBar.Value;
   b = blueTrackBar.Value;
   backgroundColor.BackColor = Color.FromArgb(r, g, b);
   DrawPicture();
   picture.Refresh();
  }

  private void button4_Click(object sender, EventArgs e)
  {
   redTrackBar.Value = 0;
   greenTrackBar.Value = 0;
   blueTrackBar.Value = 0;
   backgroundColor.BackColor = Color.White;
   DrawPicture();
   picture.Refresh();
  }

  private void ToolPanel_Scroll(object sender, ScrollEventArgs e)
  {
   /* if (e.ScrollOrientation == ScrollOrientation.VerticalScroll)
    {
     FlatSB_SetScrollPos((int)ToolPanel.Handle, SB_VERT, e.NewValue, true);
    }*/
  }

  private void Form1_ResizeEnd(object sender, EventArgs e)
  {
   /* int hei0 = ToolPanel.VerticalScroll.Minimum;
    int hei1 = ToolPanel.VerticalScroll.Maximum;
    FlatSB_SetScrollRange((int)ToolPanel.Handle, SB_VERT, hei0, hei1, true);*/
  }

  private void FillOpacityTrackBar_ValueChanged(object sender, EventArgs e)
  {
   fillOpacityEdit.Text = fillOpacityTrackBar.Value.ToString(CultureInfo.CurrentCulture);
  }

  private void FillToleranceTrackBar_ValueChanged(object sender, EventArgs e)
  {
   fillToleranceEdit.Text = fillToleranceTrackBar.Value.ToString(CultureInfo.CurrentCulture);
  }
  
  private void FillOpacityTextBox_TextChanged(object sender, EventArgs e)
  {
   fillOpacityTrackBar.Value = Convert.ToInt32(fillOpacityEdit.Text, CultureInfo.CurrentCulture);
  }

  private void FillToleranceTextBox_TextChanged(object sender, EventArgs e)
  {
   fillToleranceTrackBar.Value = Convert.ToInt32(fillToleranceEdit.Text, CultureInfo.CurrentCulture);
  }

  private void Form1_Load(object sender, EventArgs e)
  {
   //load settings
   AsciiPaint.Properties.Settings sets = AsciiPaint.Properties.Settings.Default;
   Left = sets.Left;
   Top = sets.Top;
   Width = sets.Width;
   Height = sets.Height;
  }



 }
}